package cz.edukomplex.kosilka.client.content.harmonogram;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;

import com.fredhat.gwt.xmlrpc.client.XmlRpcClient;
import com.fredhat.gwt.xmlrpc.client.XmlRpcRequest;
import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

import cz.edukomplex.kosilka.client.helpers.MyRequestBuilder;
import cz.edukomplex.kosilka.client.helpers.MyXmlRpcClient;

public class HarmonogramContent extends Composite {

	private static HarmonogramContentUiBinder uiBinder = GWT
			.create(HarmonogramContentUiBinder.class);

	interface HarmonogramContentUiBinder extends
			UiBinder<Widget, HarmonogramContent> {
	}
	
	
	@UiField SimplePanel actionPanel;
	@UiField(provided = true) CellList<HarmonogramCellListRow> harmonogramsCellList;
	@UiField(provided = true) CellTable<HarmonogramCellTableRow> harmonogramsCellTable;
	@UiField ScrollPanel cellListScrollPanel;
	@UiField SplitLayoutPanel contentContainer;
	@UiField HarmonogramUserAddPanel userAddPanel;
	@UiField Button addHarmonogramButton;
	@UiField Button editHarmonogramButton;
	@UiField Button removeHarmonogramButton;
	@UiField ScrollPanel scrollPanel;
	
	
	private ArrayList<HarmonogramCellTableRow> harmonogramCellTableArrayList = new ArrayList<HarmonogramCellTableRow>();
	private ArrayList<HarmonogramCellListRow> harmonogramCellListArrayList = new ArrayList<HarmonogramCellListRow>();
	private SingleSelectionModel<HarmonogramCellListRow> selectionModel = new SingleSelectionModel<HarmonogramCellListRow>();
	
	private static ProvidesKey<HarmonogramCellTableRow> KEY_PROVIDER = new ProvidesKey<HarmonogramCellTableRow>() {
		
		@Override
		public Object getKey(HarmonogramCellTableRow item) {
			return item.hid;
		}
	};
	
	public HarmonogramContent() {
		
		/*
		 * Inicializacia CellTable a CellList musi byt este pred initWidget()
		 */
		harmonogramsCellTable = new CellTable<HarmonogramCellTableRow>(KEY_PROVIDER);
		harmonogramsCellList = new CellList<HarmonogramCellListRow>(new HarmonogramCell());	
		initCellTable();		
		initWidget(uiBinder.createAndBindUi(this));
		
		/*
		 * RPC request, ktory ziska vsetky harmonogramy a naplni CellList
		 */
		XmlRpcClient client = MyXmlRpcClient.createClient();		
		String method = "harmonogram.fetchAll";		
		
		XmlRpcRequest<ArrayList<HashMap<String, String>>> cellListRequest = new XmlRpcRequest<ArrayList<HashMap<String, String>>>(
				client, method,null, new AsyncCallback<ArrayList<HashMap<String, String>>>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());				
			}

			@Override
			public void onSuccess(ArrayList<HashMap<String, String>> result) {				
				parseCellListXMLResponse(result);				
			}

			
		});
		cellListRequest.execute();
	}
		
		
	private void parseCellListXMLResponse(ArrayList<HashMap<String, String>> result){
		
		for (int i = 0; i < result.size(); i++) {
			HarmonogramCellListRow harmonogramCellListRow = new HarmonogramCellListRow(
					result.get(i).get("hid"), 
					result.get(i).get("harmonogram_name"), 
					result.get(i).get("cid"), 
					result.get(i).get("name"), 
					result.get(i).get("Id_oboru"), 
					result.get(i).get("Obor"), 
					result.get(i).get("date")
			);
			harmonogramCellListArrayList.add(harmonogramCellListRow);
		}
		
		initCellList();
	}

	private void parseCellTableXMLResponse(ArrayList<HashMap<String, String>> result){
		
		
		harmonogramCellTableArrayList.clear();
		
		if(result.size() > 0){
			for (Iterator iterator = result.iterator(); iterator.hasNext();) {
				@SuppressWarnings("unchecked")
				HashMap<String, String> hashMap = (HashMap<String, String>) iterator
						.next();
				
				HarmonogramCellTableRow row = new HarmonogramCellTableRow(
						hashMap.get("hid"), 
						hashMap.get("ID_st"), 
						hashMap.get("Prijmeni") + " " + hashMap.get("Jmeno"), 
						hashMap.get("ID_tr"), 
						hashMap.get("Zkratka"), 
						hashMap.get("time")
				);
				harmonogramCellTableArrayList.add(row);
			}
		}
		refreshCellTable();
		
		
	}
	
	private void initCellList() {
		
		userAddPanel.addButton.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				addStudentToHarmonogram();							
			}
			
		});
		
		userAddPanel.addAllButton.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				addGroupToHarmonogram();							
			}					
		});
		
		harmonogramsCellList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);		
				
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				userAddPanel.setVisible(true);
				userAddPanel.groupListBox.clear();
				userAddPanel.studentListBox.clear();				
				userAddPanel.setIdStudyField(selectionModel.getSelectedObject().idStudyField);
				scrollPanel.setVisible(true);
				
				Object[] params = new Object[]{Integer.parseInt(selectionModel.getSelectedObject().hid)};
				String methodName = "harmonogram.fetchHarmonogram";
				
				XmlRpcClient client = MyXmlRpcClient.createClient();				
				XmlRpcRequest<ArrayList<HashMap<String, String>>> harmonogramRequest = 
					new XmlRpcRequest<ArrayList<HashMap<String,String>>>(client, methodName, params, new AsyncCallback<ArrayList<HashMap<String,String>>>() {

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub
							
						}

						@Override
						public void onSuccess(
								ArrayList<HashMap<String, String>> result) {							
							parseCellTableXMLResponse(result);							
						}
					});
				
				harmonogramRequest.execute();
				
			}
		});
		harmonogramsCellList.setSelectionModel(selectionModel);
						
		refreshCellList();		
	}
	
	private void addStudentToHarmonogram() {
				
		/*
		 * V listobxe musi byt oznaceny student
		 */
		if(userAddPanel.studentListBox.getSelectedIndex() >= 0 ){
			String IDst = userAddPanel.studentListBox.getValue(userAddPanel.studentListBox.getSelectedIndex());			
			String hid = selectionModel.getSelectedObject().hid;
			
			XmlRpcClient client = MyXmlRpcClient.createClient();
			String methodName = "harmonogram.addStudent";
			Object[] params = new Object[]{hid,IDst};
			
			XmlRpcRequest<Boolean> addStudentRequest = new XmlRpcRequest<Boolean>(
					client, methodName, params, new AsyncCallback<Boolean>() {

						@Override
						public void onFailure(Throwable caught) {
							//TODO dorobit hlasku						
						}

						@Override
						public void onSuccess(Boolean result) {
							if(result){					
								HarmonogramCellTableRow row = new HarmonogramCellTableRow(
										selectionModel.getSelectedObject().hid,
										userAddPanel.studentListBox.getValue(userAddPanel.studentListBox.getSelectedIndex()), 
										userAddPanel.studentListBox.getItemText(userAddPanel.studentListBox.getSelectedIndex()), 
										userAddPanel.groupListBox.getValue(userAddPanel.groupListBox.getSelectedIndex()), 
										userAddPanel.groupListBox.getItemText(userAddPanel.groupListBox.getSelectedIndex()), 
										null
								);
								harmonogramCellTableArrayList.add(row);								
								refreshCellTable();
							}
						}
							
			});
			addStudentRequest.execute();			
		}		
	}
	
	/*
	 * NEFUNGUJE
	 */
	private void addGroupToHarmonogram() {
		
		String hid = selectionModel.getSelectedObject().hid;
		StringBuffer idStudents = new StringBuffer();
		final ArrayList<HarmonogramCellTableRow> rows = new ArrayList<HarmonogramCellTableRow>();
		
		/*
		 * Vyberie len studentov, ktori nie su v cellTable
		 */
		if(harmonogramCellTableArrayList.size() > 0){
			for (int i = 0; i < userAddPanel.studentListBox.getItemCount(); i++) {
				for (int j = 0; j < harmonogramCellTableArrayList.size(); j++) {
					String idStudent = userAddPanel.studentListBox.getValue(i);
					if(!harmonogramCellTableArrayList.get(j).ID_st.equals(idStudent)){
						
						HarmonogramCellTableRow row = new HarmonogramCellTableRow();														
						row.setHid(selectionModel.getSelectedObject().hid);
						row.setGroup(userAddPanel.groupListBox.getItemText(userAddPanel.groupListBox.getSelectedIndex()));
						row.setID_st(idStudent);
						row.setID_tr(userAddPanel.groupListBox.getValue(userAddPanel.groupListBox.getSelectedIndex()));
						row.setStudent(userAddPanel.studentListBox.getItemText(i));			
						rows.add(row);						
						
						idStudents.append(idStudent + ",");					
					}				
				}						
			}		
		}
		else {//ak je cellTable prazdna, tak pridaj vsetkych
			for (int i = 0; i < userAddPanel.studentListBox.getItemCount(); i++) {
				
				String idStudent = userAddPanel.studentListBox.getValue(i);
				
				HarmonogramCellTableRow row = new HarmonogramCellTableRow();														
				row.setHid(selectionModel.getSelectedObject().hid);
				row.setGroup(userAddPanel.groupListBox.getItemText(userAddPanel.groupListBox.getSelectedIndex()));
				row.setID_st(idStudent);
				row.setID_tr(userAddPanel.groupListBox.getValue(userAddPanel.groupListBox.getSelectedIndex()));
				row.setStudent(userAddPanel.studentListBox.getItemText(i));			
				rows.add(row);
				
				
				idStudents.append(idStudent + ",");									
			}
		}
		
		RequestBuilder addGroupToHarmonogramRequest = MyRequestBuilder.createService(
				RequestBuilder.POST, 
				"Harmonogram",
				"addGroupToHarmonogram"
		);
		
		try {
			addGroupToHarmonogramRequest.sendRequest("hid=" + hid + "&students="+ idStudents, new RequestCallback() {
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					Window.alert(response.getText());
					if(response.getText().equals("true")){																	
						harmonogramCellTableArrayList.addAll(rows);
						refreshCellTable();
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					// TODO Auto-generated method stub
					
				}
			});
		} catch (RequestException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void initCellTable() {
		
		
		Column<HarmonogramCellTableRow, String> studentName = new Column<HarmonogramCellTableRow, String>(new TextCell()) {
			
			@Override
			public String getValue(HarmonogramCellTableRow object) {
				return object.getStudent();
			}
		};
		
		Column<HarmonogramCellTableRow, String> group = new Column<HarmonogramCellTableRow, String>(new TextCell()) {

			@Override
			public String getValue(HarmonogramCellTableRow object) {
				return object.getGroup();
			}
		};		
		
		
		Column<HarmonogramCellTableRow, String> date = new Column<HarmonogramCellTableRow, String>(new TextCell()) {

			@Override
			public String getValue(HarmonogramCellTableRow object) {
				return object.getTime();
			}
		};
		
		Column<HarmonogramCellTableRow, String> delete = new Column<HarmonogramCellTableRow, String>(new ButtonCell()) {

			@Override
			public String getValue(HarmonogramCellTableRow object) {
				return "X";
			}
		};
		delete.setFieldUpdater(new FieldUpdater<HarmonogramCellTableRow, String>() {
			
			@Override
			public void update(int index, HarmonogramCellTableRow object, String value) {
				deleteStudentFromHarmonogram(index,object);				
			}
		});

		harmonogramsCellTable.addColumn(studentName);
		harmonogramsCellTable.addColumn(group);		
		harmonogramsCellTable.addColumn(date);
		harmonogramsCellTable.addColumn(delete);
		refreshCellTable();
		
	}
	
	private void deleteStudentFromHarmonogram(final int index,
			HarmonogramCellTableRow object) {
		
		XmlRpcClient client = MyXmlRpcClient.createClient();
		String methodName = "harmonogram.deleteStudentByHidIDst";
		Object[] params = new Object[]{object.hid,object.ID_st};
		
		XmlRpcRequest<Boolean> deleteStudentRequest = new XmlRpcRequest<Boolean>(
				client, methodName, params, new AsyncCallback<Boolean>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void onSuccess(Boolean result) {
						if(result.equals(true)){
							harmonogramCellTableArrayList.remove(index);								
							refreshCellTable();
						}						
					}				
		});		
		deleteStudentRequest.execute();	
	}

	private void refreshCellTable() {
		//nastavenie velkosti tabulky na velkost zaznamov
		harmonogramsCellTable.setPageSize(harmonogramCellTableArrayList.size());
		//Nastavnie poctu riadkov
		harmonogramsCellTable.setRowCount(harmonogramCellTableArrayList.size(), true);
	    // Obnovenie tabulky s novymi datami
		harmonogramsCellTable.setRowData(0, harmonogramCellTableArrayList);		
	}
	
	private void refreshCellList(){
				
		harmonogramsCellList.setPageSize(harmonogramCellListArrayList.size());
		harmonogramsCellList.setRowCount(harmonogramCellListArrayList.size(),true);
		harmonogramsCellList.setRowData(0, harmonogramCellListArrayList);
		
		//Nastavenie vysky laveho panelu		
		int windowHeight = Window.getClientHeight();		
		int contentPosition = contentContainer.getAbsoluteTop();
		String height = (windowHeight - contentPosition) + "px";
		contentContainer.setHeight(height);
	}
	
	@UiHandler("addHarmonogramButton")
	public void handleAddHarmonogramButton(ClickEvent e){
		new HarmonogramAddDialog(this).show();
	}
	
	
	@UiHandler("removeHarmonogramButton")
	public void handleRemoveHarmonogramButton(ClickEvent e){
		
		try{
			String harmonogramName = selectionModel.getSelectedObject().harmonogramName;			
			
			boolean confirm = Window.confirm("Chcete odstrániť harmonogram <strong>" + harmonogramName + "</strong>?");
			
			if(confirm){
				removeSelectedHarmonogram();		
			}
		} catch(NullPointerException exc){
			Window.alert("Najskôr musíte vybrať harmonogram z ľavého stĺpca");
		}
	}
	
	private void removeSelectedHarmonogram() {
		String hid = selectionModel.getSelectedObject().hid;		
		
		XmlRpcClient client = MyXmlRpcClient.createClient();
		String methodName = "harmonogram.remove";
		Object[] params = new Object[]{hid};
		XmlRpcRequest<Boolean> removeHarmonogramRequest = new XmlRpcRequest<Boolean>(
				client, methodName, params, new AsyncCallback<Boolean>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void onSuccess(Boolean result) {						
						if (result.equals(true)) {
							harmonogramCellListArrayList.remove(selectionModel.getSelectedObject());
							refreshCellList();
							selectionModel.setSelected(harmonogramCellListArrayList.get(0), true);
						}
					}
		});
		removeHarmonogramRequest.execute();		
	}

	/*
	 * Prida jednu bunku do CellList a nastavi ako vybrate
	 */
	public void addCellListRow(HarmonogramCellListRow row){		
		harmonogramCellListArrayList.add(row);//pridaj do ArrayList
		Collections.sort(harmonogramCellListArrayList);//Zorad podla abecedy (nerozlisuje male a velke pismena)
		refreshCellList();//obnov zoznam na zaklade novej hodnoty
		harmonogramsCellList.getSelectionModel().setSelected(row, true);//zvol pridanu bunku
	}
}
